﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Consul;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Hosting.Server.Features;
using Microsoft.AspNetCore.Http.Features;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;

namespace BestWise.AspNetCore.Consul.HealthCheck
{
    public static class ConsulHealthCheckExtensions
    {
        public static IApplicationBuilder RegisterWithConsul(this IApplicationBuilder app,
            IApplicationLifetime lifetime, Func<Uri, ConsulConfig, List<AgentCheckRegistration>> checkFunc = null)
        {
            var consulClient = app.ApplicationServices.GetRequiredService<IConsulClient>();
            var consulConfig = app.ApplicationServices.GetRequiredService<IOptions<ConsulConfig>>();

            // Get server address information
            var features = app.Properties["server.Features"] as FeatureCollection;
            var addresses = features.Get<IServerAddressesFeature>();
            var address = addresses.Addresses.First();
            var uri = new Uri(address);

            var checks = new List<AgentCheckRegistration>();

            if (checkFunc != null)
            {
                checks = checkFunc.Invoke(uri, consulConfig.Value);
            }

            var registration = new AgentServiceRegistration
            {
                ID = $"{consulConfig.Value.ServiceID}-{consulConfig.Value.Port}",
                Name = consulConfig.Value.ServiceName,
                Address = $"{uri.Scheme}://{consulConfig.Value.Host}",
                Port = consulConfig.Value.Port,
                Tags = consulConfig.Value.Tags,
                Checks = checks?.ToArray()
            };

            consulClient.Agent.ServiceDeregister(registration.ID).Wait();
            consulClient.Agent.ServiceRegister(registration).Wait();

            lifetime.ApplicationStopping.Register(() =>
            {
                consulClient.Agent.ServiceDeregister(registration.ID).Wait();
            });

            return app;
        }
    }
}
